package com.atguigu.tingshu.user.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.user.UserListenProcess;
import com.atguigu.tingshu.user.reporsitory.ListenReporsitory;
import com.atguigu.tingshu.user.service.UserListenProcessService;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.atguigu.tingshu.vo.user.UserListenProcessVo;
import com.mongodb.client.result.UpdateResult;
import org.joda.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@SuppressWarnings({"all"})
public class UserListenProcessServiceImpl implements UserListenProcessService {

	@Autowired
	private MongoTemplate mongoTemplate;
	@Autowired
	private ListenReporsitory listenReporsitory;
	@Autowired
	private RabbitService rabbitService;
	@Autowired
	private RedisTemplate redisTemplate;

	@Override
	public BigDecimal getTrackBreakSecond(Long userId, Long trackId) {
		UserListenProcess userListenProcess = mongoTemplate.findOne(
				new Query()
						.addCriteria(
								new Criteria()
								.where("userId").is(userId).and("trackId").is(trackId)
						),
				UserListenProcess.class);
		System.out.println(userListenProcess);
		if (userListenProcess!=null)
			return userListenProcess.getBreakSecond();
		return new BigDecimal("0.00");
	}

	@Override
	public void updateListenProcess(Long userId, UserListenProcessVo userListenProcessVo) {

		//需要记录声音的播放进度信息 前端会传过来 专辑ID 声音ID 当前播放时长 从线程变量中获取的用户ID
		//怎么存 存哪 后续相关操作
		// MongoDB 对大量数据实时进行操作  通过定义实体类进行存储 MongoDB有对应的简化CRUD操作的工具Reporsitory
		//当数据库中不存在对应的数据 通过工具进行新增 存在则进行修改 通过MongTemplate进行修改 但是template在upsert方法中 无则新增有则修噶可以简化代码
		UserListenProcess userListenProcesss = mongoTemplate.findOne(new Query().query(new Criteria().where("userId").is(userId)
						.and("albumId").is(userListenProcessVo.getAlbumId())
						.and("trackId").is(userListenProcessVo.getTrackId())),
				UserListenProcess.class
		);
		if (userListenProcesss == null){
			UserListenProcess userListenProcess = new UserListenProcess();
			userListenProcess.setUserId(userId);
			userListenProcess.setAlbumId(userListenProcessVo.getAlbumId());
			userListenProcess.setTrackId(userListenProcessVo.getTrackId());
			userListenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
			userListenProcess.setIsShow(1);
			userListenProcess.setCreateTime(new DateTime().now());
			userListenProcess.setUpdateTime(new DateTime().now());
			UserListenProcess save = listenReporsitory.save(userListenProcess);


		}
		else {
			UpdateResult upsert = mongoTemplate.updateFirst(new Query().query(new Criteria()
							.where("userId").is(userId)
							.and("albumId").is(userListenProcessVo.getAlbumId())
							.and("trackId").is(userListenProcessVo.getTrackId())),
					new Update()
							.set("breakSecond", userListenProcessVo.getBreakSecond())
							.set("updateTime", new Date().getTime()),
					UserListenProcess.class);
		}
		String key = RedisConstant.USER_TRACK_REPEAT_STAT_PREFIX + userId + ":" + userListenProcessVo.getTrackId();
		String now = DateUtil.now();
		DateTime after = DateUtil.endOfDay(new Date());
		long ttl = after.getTime() - System.currentTimeMillis();
		Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, userListenProcessVo.getTrackId(), ttl, TimeUnit.MILLISECONDS);
		if (flag){
			TrackStatMqVo trackStatMqVo = new TrackStatMqVo();
			trackStatMqVo.setTrackId(userListenProcessVo.getTrackId());
			trackStatMqVo.setCount(1);
			trackStatMqVo.setStatType(SystemConstant.TRACK_STAT_PLAY);
			trackStatMqVo.setAlbumId(userListenProcessVo.getAlbumId());
			trackStatMqVo.setBusinessNo(IdUtil.fastSimpleUUID());
			String jsonString = JSON.toJSONString(trackStatMqVo);
			rabbitService.sendMessage(MqConst.EXCHANGE_TRACK,MqConst.ROUTING_TRACK_STAT_UPDATE, jsonString);
		}


	}

	@Override
	public Map<String, Long> getLatelyTrack(Long userId) {
		Map<String, Long> map = new HashMap<>();
		List<UserListenProcess> userListenProcesses = mongoTemplate.find(new Query(new Criteria().where("userId").is(userId)).with(Sort.by(Sort.Direction.DESC, "updateTime")).limit(1), UserListenProcess.class);
		if (userListenProcesses!=null){
			UserListenProcess userListenProcess = userListenProcesses.get(0);
			map.put("albumId",userListenProcess.getAlbumId());
			map.put("trackId",userListenProcess.getTrackId());
			return map;
		}
		return null;
	}
}
